﻿Imports System
Imports System.Collections
Imports System.Threading

Namespace System.Workflow.ComponentModel
    Friend Class ActivityExecutors
        ' Methods
        Public Shared Function GetActivityExecutor(ByVal activity As Activity) As ActivityExecutor
            If (activity Is Nothing) Then
                Throw New ArgumentNullException("activity")
            End If
            Return ActivityExecutors.GetActivityExecutors(activity)(0)
        End Function

        Public Shared Function GetActivityExecutorFromType(ByVal executorType As Type) As ActivityExecutor
            If (executorType Is Nothing) Then
                Throw New ArgumentNullException("executorType")
            End If
            If Not GetType(ActivityExecutor).IsAssignableFrom(executorType) Then
                Throw New ArgumentException(SR.GetString("Error_NonActivityExecutor", New Object() { executorType.FullName }), "executorType")
            End If
            Dim executor As ActivityExecutor = [TryCast](ActivityExecutors.typeToExecutorMapping.Item(executorType),ActivityExecutor)
            If (Not executor Is Nothing) Then
                Return executor
            End If
            SyncLock ActivityExecutors.typeToExecutorMapping.SyncRoot
                executor = [TryCast](ActivityExecutors.typeToExecutorMapping.Item(executorType),ActivityExecutor)
                If (Not executor Is Nothing) Then
                    Return executor
                End If
                Thread.MemoryBarrier
                ActivityExecutors.typeToExecutorMapping.Item(executorType) = Activator.CreateInstance(executorType)
            End SyncLock
            Return DirectCast(ActivityExecutors.typeToExecutorMapping.Item(executorType), ActivityExecutor)
        End Function

        Friend Shared Function GetActivityExecutors(ByVal activity As Activity) As ActivityExecutor()
            If (activity Is Nothing) Then
                Throw New ArgumentNullException("activity")
            End If
            Dim type As Type = activity.GetType
            Dim executorArray As ActivityExecutor() = [TryCast](ActivityExecutors.executors.Item(type),ActivityExecutor())
            If (executorArray Is Nothing) Then
                SyncLock ActivityExecutors.executors.SyncRoot
                    executorArray = [TryCast](ActivityExecutors.executors.Item(type),ActivityExecutor())
                    If (Not executorArray Is Nothing) Then
                        Return executorArray
                    End If
                    Dim objArray As Object() = Nothing
                    Try 
                        objArray = ComponentDispenser.CreateActivityExecutors(activity)
                    Catch exception As Exception
                        Throw New InvalidOperationException(SR.GetString("ExecutorCreationFailedErrorMessage", New Object() { type.FullName }), exception)
                    End Try
                    If ((objArray Is Nothing) OrElse (objArray.Length = 0)) Then
                        Throw New InvalidOperationException(SR.GetString("ExecutorCreationFailedErrorMessage", New Object() { type.FullName }))
                    End If
                    executorArray = New ActivityExecutor(objArray.Length  - 1) {}
                    Dim i As Integer
                    For i = 0 To objArray.Length - 1
                        If Not ActivityExecutors.typeToExecutorMapping.Contains(objArray(i).GetType) Then
                            SyncLock ActivityExecutors.typeToExecutorMapping.SyncRoot
                                If Not ActivityExecutors.typeToExecutorMapping.Contains(objArray(i).GetType) Then
                                    Thread.MemoryBarrier
                                    ActivityExecutors.typeToExecutorMapping.Item(objArray(i).GetType) = objArray(i)
                                End If
                            End SyncLock
                        End If
                        executorArray(i) = DirectCast(ActivityExecutors.typeToExecutorMapping.Item(objArray(i).GetType), ActivityExecutor)
                    Next i
                    Thread.MemoryBarrier
                    ActivityExecutors.executors.Item(type) = executorArray
                End SyncLock
            End If
            Return executorArray
        End Function


        ' Fields
        Private Shared executors As Hashtable = New Hashtable
        Private Shared typeToExecutorMapping As Hashtable = New Hashtable
    End Class
End Namespace

